package router

import (
	"FinancialManagement/src/base/baselog"
	"FinancialManagement/src/base/config"
	"FinancialManagement/src/base/mess"
	"FinancialManagement/src/business/api"
	"FinancialManagement/src/business/util"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// JWTAuth
// @Description: 认证拦截器
// @return gin.HandlerFunc
func JWTAuth() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		// 预检请求不做认证，直接放行
		if ctx.Request.Method == http.MethodOptions {
			ctx.AbortWithStatus(http.StatusOK)
			return
		}
		// 临时放行年度分析相关接口，便于前端联调
		allowPaths := map[string]bool{
			"/" + config.Get().Base.UrlPosition + "/common/getAnnualProcurementOfVehicles": true,
			"/" + config.Get().Base.UrlPosition + "/common/getActualSalesOfVehicles":       true,
			"/" + config.Get().Base.UrlPosition + "/common/getPurchaseListOfYear":          true,
			"/" + config.Get().Base.UrlPosition + "/common/getSalesListOfYear":             true,
		}
		if allowPaths[ctx.Request.URL.Path] {
			baselog.Logger.Info("临时放行接口：" + ctx.Request.URL.Path)
			ctx.Next()
			return
		}

		baselog.Logger.Info("当前经过拦截地址是：" + ctx.Request.URL.String())
		authHeader, err := ctx.Cookie(api.TOKEN_CODE)
		if err != nil || authHeader == "" {
			uri := config.Get().Base.WebUrl + "login"
			ctx.JSON(http.StatusOK, mess.ResMessOK(uri))
			ctx.Abort() // 结束后续操作
			return
		} else {
			baselog.Logger.Debug("当前操作token", zap.String("token", authHeader), zap.String("url", ctx.Request.URL.String()))
			// 解析token包含的信息
			claims, err := util.ParseToken(authHeader)
			if err != nil {
				ctx.JSON(http.StatusOK, mess.ResErrMess(90010050027, "无效的Token"))
				ctx.Abort()
				return
			}
			baselog.Logger.Debug("当前操作人是", zap.String("userId", claims.UserId), zap.String("url", ctx.Request.URL.String()))
			// 将当前请求的claims信息保存到请求的上下文c上
			ctx.Set("claims", claims)
			ctx.Set("LoginUserId", claims.UserId)
			baselog.Logger.Debug("当前会话过期剩余时间：", zap.Int64("endTime", claims.ExpiresAt.Unix()))
			baselog.Logger.Debug("与当前时间相比，剩余时间:", zap.Int64("time", claims.ExpiresAt.Unix()-time.Now().Unix()))
			// 判断当前token是否快到期，如果快到期则调用刷新token接口，该处默认限定为1小时
			if claims.ExpiresAt.Unix()-time.Now().Unix() <= 3600 {
				baselog.Logger.Info("触发刷新token逻辑")
				token, _ := util.RefreshToken(authHeader)
				ctx.SetCookie(api.TOKEN_CODE, token, int(util.TokenExpireDuration.Seconds()), "/", config.Get().Base.Domain, false, false)
			}
			ctx.Next()
		}
	}
}
